#include "internal.h"
#include "nfc_management.h"

int desfire_send_cmd(MifareTag tag, uint8_t cmd, char *param)
{
    printf("In desfire_send_cmd\n");

    int i;
    BUFFER_INIT (res, CMD_SIZE_RX);
    BUFFER_INIT (cmd_to_send, CMD_SEND_KEY_SIZE);

    BUFFER_APPEND (cmd_to_send, 0x00);
    BUFFER_APPEND (cmd_to_send, 0xDA);
    BUFFER_APPEND (cmd_to_send, 0x01);

    printf("About to append specific command\n");

    BUFFER_APPEND (cmd_to_send, cmd);

    printf("Building command: %x\n", cmd);

    if (cmd == SEND_KEY)
    {
        if (param == NULL)
        {
            printf("ERROR - Key should not be NULL\n");
            return -1;
        }
		for (i = 0; i < KEY_SIZE; i++)
		{
		    BUFFER_APPEND (cmd_to_send, param[i]);
		}
    }

    for (i = 0; i < 20; i++)
        printf("cmd_to_send[%d] = %x\n", i, cmd_to_send[i]);

    if ((nfc_initiator_transceive_bytes(tag->device, cmd_to_send, BUFFER_SIZE(cmd_to_send), res, BUFFER_MAXSIZE(res), 300) < 0))
    {
        printf("Failed to transceive bytes\n");
        return -1;
    }

    if ((res[0] != 0x90) || (res[1] != 0x00))
    {
        printf("Failed to get correct return\n");
        return -1;
    }
    printf("Transceive passed\n");


    for (i = 0; i < BUFFER_MAXSIZE(res); i++)
        printf("res[%d] = %x\n", i, res[i]);


    return 0;
}

/*
 * Establish connection to the provided tag.
 */
int
mifare_desfire_connect (MifareTag tag, uint8_t *ret, nfc_target *tag_ptr)
{
    //ASSERT_INACTIVE (tag);
    //ASSERT_MIFARE_DESFIRE (tag);

    //nfc_target pnti;
    nfc_modulation modulation = {
	.nmt = NMT_ISO14443A,
	.nbr = NBR_424
    };

    int i;
    for (i = 0; i < tag->info.szUidLen; i++)
		printf("abtUid[%d] = %x\n", i, tag->info.abtUid[i]);
    printf("szUidLen = %x\n", tag->info.szUidLen);
    printf("device  = %x\n", tag->device);

    if (nfc_initiator_select_passive_target (tag->device, modulation, tag->info.abtUid, tag->info.szUidLen, tag_ptr) >= 0)
    {
		// The registered ISO AID of DESFire D2760000850100
		// Selecting this AID selects the MF
		BUFFER_INIT (cmd, CMD_SELECT_AID_SIZE_TX);
		BUFFER_INIT (res, CMD_SELECT_AID_SIZE_RX);

		for (i = 0; i < 18; i++)
			res[i] = 0;

		BUFFER_APPEND (cmd, 0x00);
		BUFFER_APPEND (cmd, 0xa4);
		BUFFER_APPEND (cmd, 0x04);
		BUFFER_APPEND (cmd, 0x00);
		//uint8_t AID[]={ 0xd2, 0x76, 0x00, 0x00, 0x85, 0x01, 0x00};
		//uint8_t AID[] = {0xF3, 0x07, 0x83, 0x64, 0x64, 0x64};
		uint8_t AID[] = {0xF0, 0x62, 0x63, 0x6B, 0x6A, 0x63, 0x6B, 0x68, 0x6B, 0x72, 0x73, 0x0A};
		BUFFER_APPEND (cmd, sizeof (AID));
		BUFFER_APPEND_BYTES (cmd, AID, sizeof (AID));

		for (i = 0; i < BUFFER_MAXSIZE(cmd); i++)
					printf("cmd[%d] = %x\n", i, cmd[i]);

		if ((nfc_initiator_transceive_bytes(tag->device, cmd, BUFFER_SIZE(cmd), res, BUFFER_MAXSIZE(res), 300) < 0))
		{
			printf("Failed to transceive bytes\n");
			return -1;
		}

		//for (i = 0; i < BUFFER_MAXSIZE(res); i++)
		//		printf("res[%d] = %02x\n", i, res[i]);

		if ((res[BUFFER_MAXSIZE(res) - 2] != 0x90) || (res[BUFFER_MAXSIZE(res) - 1] != 0x00))
		{
			printf("Failed to get correct return\n");
			return -1;
		}
		printf("Transceive passed\n");

		for (i = 0; i < BUFFER_MAXSIZE(res); i++)
		{
			ret[i] = res[i];
		}

		for (i = 0; i < BUFFER_MAXSIZE(res); i++)
			printf("res[%d] = %x\n", i, res[i]);

		for (i = 0; i < BUFFER_MAXSIZE(res); i++)
			printf("ret[%d] = %x\n", i, ret[i]);

		//printf("sizeof(ret) = %d\n", sizeof(ret));
		//printf("sizeof(res) = %d\n", sizeof(res));
		//ret = (uint8_t *)malloc(BUFFER_MAXSIZE(res) * sizeof(uint8_t));

		//printf("sizeof(uint8_t) = %d\n", sizeof(uint8_t));

		//free(ret);
		//ret = NULL;

		/*
		tag->active = 1;
		free (MIFARE_DESFIRE (tag)->session_key);
		MIFARE_DESFIRE (tag)->session_key = NULL;
		MIFARE_DESFIRE (tag)->last_picc_error = OPERATION_OK;
		MIFARE_DESFIRE (tag)->last_pcd_error = OPERATION_OK;
		MIFARE_DESFIRE (tag)->authenticated_key_no = NOT_YET_AUTHENTICATED;
		MIFARE_DESFIRE (tag)->selected_application = 0;
		*/
    }
    else
    {
		printf("Failed to select passive target\n");
		return -1;
    }
    printf("Connect passed\n");
    return 0;
}

/*
 * Terminate connection with the provided tag.
 */
int
mifare_desfire_disconnect (MifareTag tag)
{
    //ASSERT_ACTIVE (tag);
    //ASSERT_MIFARE_DESFIRE (tag);

    //free (MIFARE_DESFIRE (tag)->session_key);
    //MIFARE_DESFIRE(tag)->session_key = NULL;

    if (nfc_initiator_deselect_target (tag->device) >= 0)
    {
		printf("Released tag\n");
		//tag->active = 0;
    }
    return 0;
}

/*
 * Free the provided tag.
 */
void
mifare_desfire_tag_free (MifareTag tag)
{
    //free (MIFARE_DESFIRE (tag)->session_key);
    //free (MIFARE_DESFIRE (tag)->crypto_buffer);
    free (tag);
}

/*
 * Allocates and initialize a MIFARE DESFire tag.
 */
MifareTag
mifare_desfire_tag_new (void)
{
    MifareTag tag;
    /*
    if ((tag= malloc (sizeof (struct mifare_desfire_tag)))) {
	MIFARE_DESFIRE (tag)->last_picc_error = OPERATION_OK;
	MIFARE_DESFIRE (tag)->last_pcd_error = OPERATION_OK;
	MIFARE_DESFIRE (tag)->session_key = NULL;
	MIFARE_DESFIRE (tag)->crypto_buffer = NULL;
	MIFARE_DESFIRE (tag)->crypto_buffer_size = 0;
    }
    */

    if ((tag= malloc (sizeof (struct mifare_tag))))
    {
		printf("Allocated space for a DESFIRE tag\n");
	}
	else
	{
		printf("FAILED allocating space for a DESFIRE tag\n");
	}

    return tag;
}
